﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Joints;
using FarseerPhysics.Factories;
using System.Xml;
using System.Xml.Serialization;
using System.Text;
using System.IO;

namespace MountainORocks
{
    class WorldBuilder
    {


        List<GameShape> level;
        List<dropStuff> dropList;
        double timeToAddConst = 0.1;
        double timeToAdd = 0;
        MouseState mState;
        KeyboardState kState;
       // World world;
        bool createCircle = false;
        bool createRect = false;
        bool createDroper = false;
      //  bool createPlayer = false;
       // bool createDoor = false;
        int circleRadiosX = 32;
        int circleRadiosY = 32;
        int rectWidth = 32;
        int rectHigth = 32;
        int levelCount;
       // bool play = true;
       // ContactManager myContact;
        Game1 myGame;
        int playerW;
        int playerH;
        int Width;
        int Height;
       // bool isJumping = false;
        enum BuilderState { build, pickShape};
        BuilderState builderState = BuilderState.build;
        ShapeM currentM;
        ShapeType currentType;
        Player currentPlayer;
        Rectangle c_rock = new Rectangle(150,80,64,64);
        Rectangle c_wood = new Rectangle(150 + 64 + 10, 80, 64, 64);
        Rectangle c_glass = new Rectangle(150 + 64*2 + 10*2, 80, 64, 64);
        Rectangle r_rock = new Rectangle(150 + 64*0 + 10*0, 230, 64, 64);
        Rectangle r_wood = new Rectangle(150 + 64 * 1 + 10 * 1, 230, 64, 64);
        Rectangle c_random = new Rectangle(150 + 64 * 2 + 10 * 2, 230, 64, 64);
        Rectangle r_glass = new Rectangle(150 , 380, 64, 64);
        private bool press = false;
        private bool reset = false;
        

        private bool makeStatic = false;

        public WorldBuilder(int Width, int Height, int playerW, int playerH, Game1 currentGame, Player tmpPlayer)
        {
           // world = nWorld;
            level = new List<GameShape>();
            dropList = new List<dropStuff>();
            this.playerW = playerW;
            this.playerH = playerH;
            myGame = currentGame;
            this.Height = Height;
            this.Width = Width;
            currentPlayer = tmpPlayer;
           // newWorld();


        }

        public int count { get {return levelCount; } }

        public void update(GameTime gameTime)
        {
            switch (builderState)
            {
                
                case BuilderState.build:
                    {
                        if (myGame.Refresh) 
                        {
                            myGame.setRefresh();
                            myGame.buildWorld();
                            level.Clear(); 
                        }
                        timeToAdd -= gameTime.ElapsedGameTime.TotalSeconds;
                        if ((Keyboard.GetState().IsKeyDown(Keys.R) | Keyboard.GetState().IsKeyDown(Keys.Escape)) && (!reset))
                        {
                            myGame.buildWorld();
                            level.Clear();
                            reset = true;
                        }
                        if ((Keyboard.GetState().IsKeyUp(Keys.R) && (reset) | Keyboard.GetState().IsKeyUp(Keys.Escape))) { reset = false; }
                        if ((timeToAdd < 0) && (Keyboard.GetState().IsKeyUp(Keys.Space)) && (press))
                            press = false;
                        if ((timeToAdd < 0) && (Keyboard.GetState().IsKeyDown(Keys.Space)) && (!press))
                        {
                            builderState = BuilderState.pickShape;
                            press = true;
                        }
                        
                        mState = Mouse.GetState();
                        kState = Keyboard.GetState();

                        if (kState.IsKeyDown(Keys.Enter))
                        {
                            myGame.setBuilding();
                            LevelData save = new LevelData();
                            save.getDate(level, dropList,myGame.getRocks);
                            
                            save.getPlayerLoc(myGame.charBody.Position.X, myGame.charBody.Position.Y);
                            saveLevel(save);
                            myGame.gameState = Game1.GameState.menu;


                        }

                        if ((createCircle) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Up))))
                        {
                            circleRadiosY += 2;
                            circleRadiosX += 2;
                        }

                        if ((createCircle) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Right))))
                        {
                            circleRadiosX += 2;
                            circleRadiosY += 2;
                        }

                        if ((createCircle) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Down)) || (kState.IsKeyDown(Keys.Left))))
                        {
                            circleRadiosY -= 2;
                            circleRadiosX -= 2;
                            if (circleRadiosY < 0)
                                circleRadiosY = 0;
                            if (circleRadiosX < 0)
                                circleRadiosX = 0;

                        }

                        if ((createCircle) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Left))))
                        {
                            circleRadiosX -= 2;
                            circleRadiosY -= 2;
                            if (circleRadiosY < 0)
                                circleRadiosY = 0;
                            if (circleRadiosX < 0)
                                circleRadiosX = 0;
                        }

                        if ((createRect) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Down))))
                        {
                            rectHigth -= 2;
                            if (rectHigth < 0)
                                rectHigth = 0;
                        }

                        if ((createRect) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Up))))
                        {
                            rectHigth += 2;
                        }

                        if ((createRect) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Right))))
                        {
                            rectWidth += 2;
                        }

                        if ((createRect) && (mState.LeftButton != ButtonState.Pressed) && ((kState.IsKeyDown(Keys.Left))))
                        {
                            rectWidth -= 2;
                            if (rectWidth < 0)
                                rectWidth = 0;
                        }

                        if ((timeToAdd<0) && (createRect) && (mState.LeftButton == ButtonState.Pressed))
                        {

                            level.Add(new GameShape(myGame.world, currentType, currentM, new Rectangle(mState.X, mState.Y, rectWidth, rectHigth), makeStatic));
                            createRect = false;
                            timeToAdd = timeToAddConst;
                            rectWidth = 32;
                            rectHigth = 32;
                            makeStatic = false;
                        }

                        if ((timeToAdd<0) && (createCircle) && (mState.LeftButton == ButtonState.Pressed))
                        {

                            level.Add(new GameShape(myGame.world, currentType, currentM, new Rectangle(mState.X, mState.Y, circleRadiosX, circleRadiosY), makeStatic));
                            createCircle = false;
                            circleRadiosY = 32;
                            circleRadiosX = 32;
                            timeToAdd = timeToAddConst;
                            makeStatic = false;
                        }

                        if ((timeToAdd < 0) && (createDroper) && (mState.LeftButton == ButtonState.Pressed))
                        {

                            createDroper = false;
                            dropList.Add(new dropStuff(new Vector2(64, 64), false, -3, -1, myGame, mState.X, mState.Y,true));
                            timeToAdd = timeToAddConst;
                            makeStatic = false;
                        }

                        if ((!createCircle) && (!createRect) && (!createDroper) && (mState.RightButton == ButtonState.Pressed))
                        { // delete the pressed shape
                            Fixture savedFixture2 = myGame.world.TestPoint(new Vector2(mState.X, mState.Y));
                            if (savedFixture2 != null)
                            {
                                foreach (GameShape shape in level)
                                {
                                    if (shape.body == savedFixture2.Body)
                                    {
                                        shape.body.Awake = true;
                                        level.Remove(shape);
                                        myGame.world.RemoveBody(shape.body);

                                        // rewake all the world 
                                        foreach (GameShape shape2 in level)
                                        {
                                            shape2.body.Awake = true;
                                        }
                                        break;
                                    }

                                }
                            }


                        }

                        if (!createCircle && !createRect && !createDroper && kState.IsKeyDown(Keys.M))
                        {
                            makeStatic = true;
                        }

                        if (makeStatic && (mState.LeftButton == ButtonState.Pressed))
                        {
                            // look for what shape you pressed
                            Fixture savedFixture = myGame.world.TestPoint(new Vector2(mState.X, mState.Y));
                            if (savedFixture != null)
                            {
                                foreach (GameShape shape in level)
                                {
                                    if (shape.body == savedFixture.Body)
                                    {
                                        shape.body.IsStatic = !shape.body.IsStatic;
                                        makeStatic = false;

                                        break;
                                    }

                                }
                            }
                        }

                        if ((!createCircle) && (!createRect) && (!createDroper))
                        {
                            currentPlayer.Update(gameTime);
                        }

                       // if (play)
                            myGame.world.Step((float)gameTime.ElapsedGameTime.TotalSeconds);

                        break;
                    }
                case BuilderState.pickShape:
                    {
                        if ((timeToAdd < 0) && (Keyboard.GetState().IsKeyUp(Keys.Space)) && (press))
                            press = false;
                        if ((timeToAdd < 0) && (Keyboard.GetState().IsKeyDown(Keys.Space)) && (!press))
                        {
                            builderState = BuilderState.build;
                            press = true;
                        }

                        createRect = false;
                        createCircle = false;
                        timeToAdd -= gameTime.ElapsedGameTime.TotalSeconds;
                        if ((timeToAdd<0) && (Mouse.GetState().LeftButton == ButtonState.Pressed))
                        {
                            MouseState myMouse = Mouse.GetState();
                            if (r_wood.Contains(myMouse.X, myMouse.Y))
                            {
                                currentM = ShapeM.Wood;
                                currentType = ShapeType.Rect;
                                createRect = true;
                                timeToAdd = timeToAddConst;
                                builderState = BuilderState.build;
                            }

                            if (r_rock.Contains(myMouse.X, myMouse.Y))
                            {
                                currentM = ShapeM.Stone;
                                currentType = ShapeType.Rect;
                                createRect = true;
                                timeToAdd = timeToAddConst;
                                builderState = BuilderState.build;
                            }

                            if (c_glass.Contains(myMouse.X, myMouse.Y))
                            {
                                currentM = ShapeM.Glass;
                                currentType = ShapeType.Circle;
                                createCircle = true;
                                timeToAdd = timeToAddConst;
                                builderState = BuilderState.build;
                            }

                            if (c_wood.Contains(myMouse.X, myMouse.Y))
                            {
                                currentM = ShapeM.Wood;
                                currentType = ShapeType.Circle;
                                createCircle = true;
                                timeToAdd = timeToAddConst;
                                builderState = BuilderState.build;
                            }

                            if (c_rock.Contains(myMouse.X, myMouse.Y))
                            {
                                currentM = ShapeM.Stone;
                                currentType = ShapeType.Circle;
                                createCircle = true;
                                timeToAdd = timeToAddConst;
                                builderState = BuilderState.build;
                            }

                            if (c_random.Contains(myMouse.X, myMouse.Y))
                            {
                                createDroper = true;
                                timeToAdd = timeToAddConst;
                                builderState = BuilderState.build;
                            }
                            if (r_glass.Contains(myMouse.X, myMouse.Y))
                            {
                                currentM = ShapeM.Glass;
                                currentType = ShapeType.Rect;
                                createRect = true;
                                timeToAdd = timeToAddConst;
                                builderState = BuilderState.build;
                            }

                        }

                        break;
                    }



            }

        }


       

        public void newWorld()
        {
            myGame.buildWorldEmpty();

        }

     /*   bool charBody_OnCollision(Fixture fixtureA, Fixture fixtureB, FarseerPhysics.Dynamics.Contacts.Contact contact)
        {
            if (fixtureB.Body == charBody)
            {
                if ((fixtureA.Body.Position.Y > fixtureB.Body.Position.Y + 31))
                    isJumping = false;
                if (fixtureB.Body.Position.Y > Height - 35)
                    isJumping = false;
            }
            if (fixtureA.Body == charBody)
            {
                if ((fixtureB.Body.Position.Y > fixtureA.Body.Position.Y + 31))
                    isJumping = false;
                if (fixtureA.Body.Position.Y > Height - 35)
                    isJumping = false;

            }
            return true;
        }
        */

        public void draw(SpriteBatch spriteBatch)
        {
            if (builderState == BuilderState.build)
            {
                if (createCircle)
                {
                    switch (currentM)
                    {
                        case ShapeM.Glass:
                            {
                                spriteBatch.Draw(GameShape.CircleGlassTexture, new Rectangle(mState.X - circleRadiosX / 2, mState.Y - circleRadiosY / 2, circleRadiosX, circleRadiosY), Color.White);
                                break;
                            }
                        case ShapeM.Stone:
                            {
                                spriteBatch.Draw(GameShape.CircleRockTexture, new Rectangle(mState.X - circleRadiosX / 2, mState.Y - circleRadiosY / 2, circleRadiosX, circleRadiosY), Color.White);
                                break;
                            }
                        case ShapeM.Wood:
                            {
                                spriteBatch.Draw(GameShape.CircleWoodTexture, new Rectangle(mState.X - circleRadiosX / 2, mState.Y - circleRadiosY / 2, circleRadiosX, circleRadiosY), Color.White);
                                break;
                            }
                    }
                }

                if (createRect)
                {
                    switch (currentM)
                    {

                        case ShapeM.Stone:
                            {
                                spriteBatch.Draw(GameShape.SquareRockTexture, new Rectangle(mState.X, mState.Y, rectWidth, rectHigth), Color.White);
                                break;
                            }
                        case ShapeM.Wood:
                            {
                                spriteBatch.Draw(GameShape.SquareWoodTexture, new Rectangle(mState.X, mState.Y, rectWidth, rectHigth), Color.White);
                                break;
                            }
                        case ShapeM.Glass:
                            {
                                spriteBatch.Draw(GameShape.SquareGlassTexture, new Rectangle(mState.X, mState.Y, rectWidth, rectHigth), Color.White);
                                break;
                            }
                    }

                }

                foreach (GameShape item in level)
                {
                    item.draw(spriteBatch);
                }

                currentPlayer.draw(spriteBatch);

                spriteBatch.Draw(myGame.exitTexture,
                                       new Rectangle((int)myGame.exitDoor.Position.X, (int)myGame.exitDoor.Position.Y, 32, 32), null,
                                       Color.White, 0.0f, new Vector2(0, 0), SpriteEffects.None, 0.8f);

            }
            else
            {

                spriteBatch.Draw(myGame.rockCirTexture, c_rock, Color.White);
                spriteBatch.Draw(myGame.woodCirTexture, c_wood, Color.White);
                spriteBatch.Draw(myGame.glassCirTexture, c_glass, Color.White);
                spriteBatch.Draw(myGame.rockSquTexture, r_rock, Color.White);
                spriteBatch.Draw(myGame.woodSquTexture, r_wood, Color.White);
                spriteBatch.Draw(myGame.droperTexture, c_random, Color.White);
                spriteBatch.Draw(myGame.glassRecTexture, r_glass, Color.White);

            }
        }




        public void saveLevel(LevelData myLevel)
        {
            if (Directory.Exists(myGame.Content.RootDirectory + @"\Levels") == false)
            {
                Directory.CreateDirectory(myGame.Content.RootDirectory + @"\Levels");
            }
             
            string[] ans = Directory.GetFiles(myGame.Content.RootDirectory + @"\Levels");
            levelCount = ans.Length + 1;
            myLevel.getCount(levelCount);
            if (myGame.getDirty)
            {
                FileStream file = File.Open(myGame.Content.RootDirectory + @"\Levels\myfile" + myGame.Level.ToString() + ".xml", FileMode.Truncate);
                XmlSerializer serialize = new XmlSerializer(typeof(LevelData));
                serialize.Serialize(file, myLevel);
                file.Close();
            }
            else
            {
                FileStream file = File.Open(myGame.Content.RootDirectory + @"\Levels\myfile" + levelCount.ToString() + ".xml", FileMode.CreateNew);
                XmlSerializer serialize = new XmlSerializer(typeof(LevelData));
                serialize.Serialize(file, myLevel);
                file.Close();
            }
            
            myGame.setDirty();
        }









    }
}
